// selfpool.c
#include "selfpool.h"
#include <errno.h>

// 初始化线程池
threadpool_t *threadpool_init(int min_threads, int max_threads)
{
    // 参数校验
    if (min_threads <= 0 || max_threads <= 0 || min_threads > max_threads)
    {
        fprintf(stderr, "[ERROR] Invalid thread count parameters (min:%d, max:%d)\n",
                min_threads, max_threads);
        return NULL;
    }
    // 分配线程池结构体
    threadpool_t *pool = (threadpool_t *)malloc(sizeof(threadpool_t));
    if (!pool)
    {
        fprintf(stderr, "[FATAL] Failed to allocate thread pool\n");
        return NULL;
    }
    // 初始化同步原语
    if (pthread_mutex_init(&pool->mutex, NULL) != 0 ||
        pthread_cond_init(&pool->cond, NULL) != 0)
    {
        free(pool);
        fprintf(stderr, "[FATAL] Failed to initialize synchronization primitives\n");
        return NULL;
    }
    // 分配线程数组（初始大小为max_threads）
    pool->threads = (pthread_t *)malloc(sizeof(pthread_t) * max_threads);
    if (!pool->threads)
    {
        pthread_mutex_destroy(&pool->mutex);
        pthread_cond_destroy(&pool->cond);
        free(pool);
        fprintf(stderr, "[FATAL] Failed to allocate thread array\n");
        return NULL;
    }
    // 初始化成员变量
    pool->queue_head = pool->queue_tail = NULL;
    pool->thread_count = 0;
    pool->min_thread_count = min_threads;
    pool->max_thread_count = max_threads;
    pool->task_count = 0;
    pool->idle_thread_count = 0;
    pool->shutdown = 0;
    pool->active_thread_count = 0;
    // 创建初始线程
    for (int i = 0; i < min_threads; i++)
    {
        if (pthread_create(&pool->threads[i], NULL, worker, pool) != 0)
        {
            fprintf(stderr, "[ERROR] Failed to create initial thread %d\n", i);
            threadpool_destroy(pool);
            return NULL;
        }
        pool->thread_count++;
    }
    return pool;
}

// 工作线程函数
void *worker(void *arg)
{
    threadpool_t *pool = (threadpool_t *)arg;
    threadpool_task_t *task = NULL;
    while (1)
    {
        pthread_mutex_lock(&pool->mutex);
        // 注册空闲线程
        pool->idle_thread_count++;
        // 等待任务或退出条件
        while (pool->task_count == 0 && !pool->shutdown)
        {
            // 动态缩减检查：当空闲超过最小线程时
            if (pool->thread_count > pool->min_thread_count &&
                pool->idle_thread_count > (pool->thread_count / 2))
            {
                pool->thread_count--;
                pool->idle_thread_count--;
                pthread_mutex_unlock(&pool->mutex);
                pthread_exit(NULL);
            }
            pthread_cond_wait(&pool->cond, &pool->mutex);
        }

        // 处理关闭请求
        if (pool->shutdown)
        {
            pool->thread_count--;
            pool->idle_thread_count--;
            pthread_mutex_unlock(&pool->mutex);
            pthread_exit(NULL);
        }

        // 获取任务
        pool->idle_thread_count--;
        task = pool->queue_head;
        if (task)
        {
            pool->task_count--;
            pool->queue_head = task->next;
            if (!pool->queue_head)
                pool->queue_tail = NULL;
        }
        pthread_mutex_unlock(&pool->mutex);
        // 执行任务
        if (task)
        {
            // 更新活跃计数
            pthread_mutex_lock(&pool->mutex);
            pool->active_thread_count++;
            pthread_mutex_unlock(&pool->mutex);
            // 执行主任务
            if (task->function)
                task->function(task->argument);
            // 执行回调
            if (task->callback)
                task->callback(task->argument);
            // 清理任务
            free(task);
            task = NULL;
            // 更新活跃计数
            pthread_mutex_lock(&pool->mutex);
            pool->active_thread_count--;
            pthread_mutex_unlock(&pool->mutex);
        }
    }
    return NULL;
}

// 添加任务（优化版）
void threadpool_add_task(threadpool_t *pool, void (*task_func)(void *),
                         void *arg, void (*callback)(void *), int priority)
{
    // 参数校验
    if (!pool || !task_func)
    {
        fprintf(stderr, "[WARN] Invalid task parameters\n");
        return;
    }
    // 创建任务节点
    threadpool_task_t *new_task = (threadpool_task_t *)malloc(sizeof(threadpool_task_t));
    if (!new_task)
    {
        fprintf(stderr, "[ERROR] Failed to allocate task\n");
        return;
    }
    new_task->function = task_func;
    new_task->argument = arg;
    new_task->callback = callback;
    new_task->priority = priority;
    new_task->next = NULL;
    pthread_mutex_lock(&pool->mutex);
    // 插入任务到优先队列
    if (!pool->queue_head || priority < pool->queue_head->priority)
    {
        new_task->next = pool->queue_head;
        pool->queue_head = new_task;
        if (!pool->queue_tail)
            pool->queue_tail = new_task;
    }
    else
    {
        threadpool_task_t *current = pool->queue_head;
        while (current->next && current->next->priority <= priority)
        {
            current = current->next;
        }
        new_task->next = current->next;
        current->next = new_task;
        if (!new_task->next)
            pool->queue_tail = new_task;
    }
    pool->task_count++;

    // 动态扩展线程
    if (pool->thread_count < pool->max_thread_count &&
        pool->idle_thread_count == 0)
    {
        int create_num = 1; // 保守策略：每次最多新增1个线程
        for (int i = 0; i < create_num && pool->thread_count < pool->max_thread_count; i++)
        {
            if (pthread_create(&pool->threads[pool->thread_count], NULL, worker, pool) == 0)
            {
                pool->thread_count++;
            }
            else
            {
                fprintf(stderr, "[ERROR] Failed to create thread %d\n", pool->thread_count);
                break;
            }
        }
    }
    pthread_cond_signal(&pool->cond);
    pthread_mutex_unlock(&pool->mutex);
}

// 获取状态信息
int threadpool_get_status(threadpool_t *pool, threadpool_status_t *status)
{
    if (!pool || !status)
        return -1;
    pthread_mutex_lock(&pool->mutex);
    status->thread_count = pool->thread_count;
    status->task_count = pool->task_count;
    status->idle_thread_count = pool->idle_thread_count;
    pthread_mutex_unlock(&pool->mutex);
    return 0;
}

// 调整线程池参数（增强版）
int threadpool_adjust(threadpool_t *pool, int min_threads, int max_threads)
{
    if (!pool || min_threads < 1 || max_threads < min_threads)
    {
        fprintf(stderr, "[ERROR] Invalid adjustment parameters\n");
        return -1;
    }
    pthread_mutex_lock(&pool->mutex);
    // 调整最小线程数
    if (min_threads > pool->max_thread_count)
    {
        min_threads = pool->max_thread_count;
    }
    pool->min_thread_count = min_threads;
    // 调整最大线程数并重新分配数组
    if (max_threads != pool->max_thread_count)
    {
        pthread_t *new_threads = realloc(pool->threads, max_threads * sizeof(pthread_t));
        if (!new_threads)
        {
            fprintf(stderr, "[ERROR] Failed to resize thread array\n");
            pthread_mutex_unlock(&pool->mutex);
            return -1;
        }
        pool->threads = new_threads;
        pool->max_thread_count = max_threads;
    }
    // 强制缩减线程数
    if (pool->thread_count > max_threads)
    {
        int excess = pool->thread_count - max_threads;
        pool->thread_count = max_threads;
        pthread_cond_broadcast(&pool->cond); // 唤醒多余线程退出
    }
    pthread_mutex_unlock(&pool->mutex);
    return 0;
}

// 安全销毁线程池
void threadpool_destroy(threadpool_t *pool)
{
    if (!pool)
        return;
    // 设置关闭标志
    pthread_mutex_lock(&pool->mutex);
    pool->shutdown = 1;
    pthread_cond_broadcast(&pool->cond);
    int remaining = pool->thread_count;
    pthread_mutex_unlock(&pool->mutex);
    // 等待所有线程退出
    for (int i = 0; i < remaining; i++)
    {
        if (i < pool->max_thread_count)
        { // 防止数组越界
            pthread_join(pool->threads[i], NULL);
        }
    }
    // 清理任务队列
    pthread_mutex_lock(&pool->mutex);
    threadpool_task_t *task = pool->queue_head;
    while (task)
    {
        threadpool_task_t *next = task->next;
        free(task);
        task = next;
    }
    pthread_mutex_unlock(&pool->mutex);
    // 释放资源
    free(pool->threads);
    pthread_mutex_destroy(&pool->mutex);
    pthread_cond_destroy(&pool->cond);
    free(pool);
}